package com.hjx.movie.core.system.service.admin.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hjx.movie.common.utils.ResultType;
import com.hjx.movie.common.utils.exceptions.CustomException;
import com.hjx.movie.core.system.service.admin.IRoleApiService;
import com.hjx.movie.core.util.cache.CacheKey;
import com.hjx.movie.core.util.cache.CacheUtil;
import com.hjx.movie.persistence.system.mapper.IvyRoleApiMapper;
import com.hjx.movie.persistence.system.model.IvyRoleApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>Title:</p>
 * <p>Description:</p>
 *
 * @author hjx
 * @date 2021/1/25 - 17:44
 */
@Slf4j
@Service
@Transactional
@CacheConfig(cacheNames = "IvyMovie:SpringCache:RoleApiCache",keyGenerator = "cacheKeyGenerator")
public class RoleApiService extends ServiceImpl<IvyRoleApiMapper, IvyRoleApi> implements IRoleApiService {
    @Resource
    private CacheUtil<IvyRoleApi> cacheUtil;
    public static final String ROLE_API_KEY = CacheUtil.cacheNameFormat(CacheKey.SYSTEM.getName(),CacheKey.ROLE_API.getName());
    public static final String ROLE_API_CACHE_DATA = CacheUtil.cacheNameFormat(CacheKey.SYSTEM.getName(),CacheKey.ROLE_API.getName(),CacheKey.PRE_SAVE_ROLE_API.getName());

    @Cacheable(unless = "#result==null")
    @Override
    public List<Long> findApiByRoleId(Long roleId) {
        List<IvyRoleApi> roleApis = cacheUtil.getCacheList(ROLE_API_CACHE_DATA);
        return roleApis.stream().filter(item->item.getRoleId().equals(roleId))
                .map(IvyRoleApi::getApiId).collect(Collectors.toList());
    }

    @Caching(evict = {
            @CacheEvict(value="IvyMovie:SpringCache:AuthCache",allEntries = true, beforeInvocation = true),
            @CacheEvict(value = "IvyMovie:SpringCache:RoleApiCache",allEntries = true,beforeInvocation = true)
    })
    @Override
    public boolean addOrDeleteApiBatch(Long roleId, Set<Long> apiIds) {
        List<IvyRoleApi> roleApis = cacheUtil.getCacheList(ROLE_API_CACHE_DATA);
        Set<Long> rawApis =  roleApis.stream()
                .filter(item->item.getRoleId().equals(roleId))
                .map(IvyRoleApi::getApiId).collect(Collectors.toSet());
        addRoleApiBatch(roleId,apiIds,rawApis);
        deleteRoleApiBatch(roleId,apiIds,rawApis);
        return true;
    }

    /**
     * 角色新增接口访问权限
     * @param roleId 角色ID
     * @param apiIds 改变后的api权限id列表
     * @param rawApis 原本的api权限id列表
     * @return 布尔值
     */
    public void addRoleApiBatch(Long roleId, Set<Long> apiIds,Set<Long> rawApis) {
        Set<Long> copyApiIds = new HashSet<>(apiIds);
        Set<Long> copyRawApiIds = new HashSet<>(rawApis);
        // Set集合做差集 获取新增的apiId
        copyApiIds.removeAll(copyRawApiIds);
        if (copyApiIds.isEmpty()) {
            return;
        }
        log.debug("新增角色接口权限入参===>角色标识:{},新增接口标识为:{}",roleId,copyApiIds);
        List<IvyRoleApi> addRoleApis = copyApiIds.stream().map(apiId -> {
            IvyRoleApi ra = new IvyRoleApi();
            ra.setRoleId(roleId);
            ra.setApiId(apiId);
            ra.setStatus(true);
            return ra;
        }).collect(Collectors.toList());
        if(saveBatch(addRoleApis)){
            for (IvyRoleApi roleApi:addRoleApis){
                cacheUtil.getOpsForHash().put(ROLE_API_CACHE_DATA,roleApi.getRoleApiId().toString(),roleApi);
            }
        }else {
            throw new CustomException(ResultType.USER_INPUT_ERROR,"角色新增接口权限失败");
        }

    }
    /**
     * 角色删除接口访问权限
     * @param roleId 角色ID
     * @param apiIds 改变后的api权限id列表
     * @param rawApis 原本的api权限id列表
     * @return 布尔值
     */
    public void deleteRoleApiBatch(Long roleId, Set<Long> apiIds,Set<Long> rawApis) {
        Set<Long> copyApiIds = new HashSet<>(apiIds);
        Set<Long> copyRawApiIds = new HashSet<>(rawApis);
        copyRawApiIds.removeAll(copyApiIds);
        if (copyRawApiIds.isEmpty()){
            return;
        }
        log.debug("删除角色接口权限入参===>角色标识:{},删除的接口标识为:{}",roleId,copyRawApiIds);
        List<IvyRoleApi> roleApis = cacheUtil.getCacheList(ROLE_API_CACHE_DATA);
        List<String> removeApiIds = roleApis.stream()
                .filter(item ->item.getRoleId().equals(roleId)&&copyRawApiIds.contains(item.getApiId()))
                .map(item -> item.getRoleApiId().toString()).collect(Collectors.toList());
        if (removeByIds(removeApiIds)){
            cacheUtil.getOpsForHash().delete(ROLE_API_CACHE_DATA, removeApiIds.toArray());
        }else {
            throw new CustomException(ResultType.USER_INPUT_ERROR,"角色删除接口权限失败");
        }

    }


}
